package com.sun.config;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

public abstract class ExternalConfigFile {
	
	final static String LOG_TAG = "ExConfig";
	
	final public static String KEY_CFG_SWITCH = "debugOpen";
	final public static String KEY_CFG_IMSI = "imsi";
	
	final public static String FILE_SUFFIX = "cfg";
	
	final private static String DEF_NAME = "DEFAULT";

	HashMap<String, String> dataParsed = new HashMap<String, String>();
	
	public ExternalConfigFile(String fileName, Context context){
		this(fileName, null, context);
	}
	
	public ExternalConfigFile(String fileName, Object usrData, Context context){
		String keyField;
		String cfgFileName;
		if(null != fileName){
			keyField = fileName;
			cfgFileName = fileName + "." + FILE_SUFFIX;
		}else{
			keyField = DEF_NAME;
			cfgFileName = DEF_NAME + "." + FILE_SUFFIX;
		}
		File cfgFile = new File(Environment.getExternalStorageDirectory(), cfgFileName);
		Log.i(LOG_TAG, "config file name = " + cfgFileName + "field = " + keyField);
		try {
			InputStream s = new FileInputStream(cfgFile);
			if(!parseConfigFile(s, dataParsed, keyField)){
				dataParsed.clear();
			}
			s.close();
		} catch (FileNotFoundException e) {
			Log.i(LOG_TAG, "not found config file");
		} catch (IOException e) {
			e.printStackTrace();
		}
		debugKeySet(dataParsed);
		if(dataParsed.isEmpty() || !debugModeOpen()){
			dataParsed = null;
			onFindCfgFile(false, usrData);
		}else{
			onFindCfgFile(true, usrData);
		}
	}
	
	final public Object getCfg(String name, Object def){
		if(null == dataParsed)return def;
		Object obj = dataParsed.get(name);
		if(null != obj){
			return obj;
		}
		return def;
	}
	
	final public boolean debugModeOpen(){
		return Convert.toBoolean(getCfg(KEY_CFG_SWITCH, false));
	}
	
	final public String getImsi(String def){
		return Convert.toString(getCfg(KEY_CFG_IMSI, def));
	}

	/**
	 * set debug key by code
	 */
	abstract protected void debugKeySet(HashMap<String, String> data);
	
	abstract protected void onFindCfgFile(boolean isFound, Object usrData);
	
	/****************************************
	 * file data parse
	 ***************************************/
	private boolean parseConfigFile(InputStream in, HashMap<String, String> data, String key){
		boolean findField = false;
		boolean parseOk = false;
		boolean done = false;
		XmlPullParser parser = XmlHelper.createParser(in, "UTF-8");
		if(null != parser){
			try{
				int eventType = parser.getEventType();
				while (!done && eventType != XmlPullParser.END_DOCUMENT) {
					switch (eventType) {
					case XmlPullParser.START_TAG:
						if(findField){
							parseOk = parseText(parser, data) || parseOk;
						}else{
							if(parser.getName().equalsIgnoreCase(key)){
								findField = true;
							}
						}
						break;
					case XmlPullParser.END_TAG:
						if(parser.getName().equalsIgnoreCase(key)){
							done = true;
						}
						break;
					default:
						break;
					}
					eventType = parser.next();
				}

			} catch (XmlPullParserException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return findField || parseOk;
		
	}
	
	private boolean parseText(XmlPullParser parser, HashMap<String, String> out) throws Exception {
        boolean done = false;  
        boolean ret = false;
        String tag = parser.getName();
        while (!done) {  
            int eventType = parser.next();  
            if (eventType == XmlPullParser.TEXT) {
            	String val = parser.getText();
            	if(null != val){
            		out.put(tag, val);
            		ret = true;
            	}
            } else if (eventType == XmlPullParser.END_TAG) {
                if (parser.getName().equals(tag)) {
                	tag = null;
                    done = true;  
                }  
            }  
        } 
        return ret;
    }  
}
